	//
	//  InterfaceBuilder.m
	//  ExamineLine2 WatchKit Extension
	//
	//  Created by GikkiAres on 2020/2/27.
	//  Copyright © 2020 Gtmc. All rights reserved.
	//

#import "JsRequestBuilder.h"
#import "JsRequestConfig.h"
#import <sys/utsname.h>
	//依赖版本JsAfNetworking-4.0.1
#import "JsAfNetworking.h"
#import "JsRequestUtil.h"
@interface JsRequestBuilder(){
	
}


@end


@implementation JsRequestBuilder

static JsRequestBuilder * _sharedInstance;
+(instancetype)sharedInstance {
	static dispatch_once_t onceToken;
	dispatch_once(&onceToken, ^{
		_sharedInstance = [[JsRequestBuilder alloc] init];
	});
	return _sharedInstance;
}



- (NSURLSessionDataTask *)invokeDataTaskWithConfig:(JsRequestConfig *)config info:(JsRequestInfo *)info completionHandler:(JsResponseHandler)handler {
	switch(config.requestMethod) {
		case JsRequestMethodGet:
			return [self getRequestWithRequestConfig:config info:info completion:handler];
		case JsRequestMethodPost:{
			switch(config.requestBodyInputType) {
				case JsRequestBodyInputTypeNone:
				case JsRequestBodyInputTypeData:{
					return [self postRequestByRawDataRequestConfig:config completion:handler];
				}
				case JsRequestBodyInputTypeMapToJson:{
					return [self postRequestByJsonWithRequestConfig:config completion:handler];
				}
				case JsRequestBodyInputTypeMapToFormdata:{
					return [self postRequestByFormDataWithRequestConfig:config completion:handler];
				}
				case JsRequestBodyInputTypeMapToUrlEncoded:{
					return [self postRequestByUrlencodedWithRequestConfig:config completion:handler];
				}
				//TOOD: 补充该分支.
			}
		}
		case JsRequestMethodDelete: {
				
		}
		case JsRequestMethodHead:
		case JsRequestMethodOptions:
		case JsRequestMethodPut:
		case JsRequestMethodPatch:
		
		case JsRequestMethodTrace:
		case JsRequestMethodConnect:{
			return nil;
		}
	}
}

/**
 解析方式:
 req: urlencoding
 res: urlencoding
 */
+ (JsAfHTTPSessionManager *)sharedManager {
	static JsAfHTTPSessionManager * _sharedManager = nil;
	static dispatch_once_t onceToke;
	dispatch_once(&onceToke, ^{
		_sharedManager = [JsAfHTTPSessionManager manager];
		
		_sharedManager.requestSerializer = [JsAfHTTPRequestSerializer serializer];
		[_sharedManager.requestSerializer setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
		
		//如何解析返回,也需要在这里定义
		JsAfHTTPResponseSerializer *responseSerializer = [JsAfHTTPResponseSerializer serializer];
		_sharedManager.responseSerializer = responseSerializer;
		_sharedManager.responseSerializer.acceptableContentTypes =
		[NSSet setWithObjects:@"application/json", @"text/json",
		 @"text/javascript", @"text/html",
		 @"text/plain", nil];
	});
	return _sharedManager;
}


//req
//res 需要解析为json
+ (JsAfHTTPSessionManager *) sharedRawReqJsonResManager {
	static JsAfHTTPSessionManager * _rawReqJsonResManager = nil;
	static dispatch_once_t onceToke;
	dispatch_once(&onceToke, ^{
		_rawReqJsonResManager = [JsAfHTTPSessionManager manager];
		
		_rawReqJsonResManager.requestSerializer = [JsAfHTTPRequestSerializer serializer];
		//TODO: 这里需要更改...
//		[_rawReqJsonResManager.requestSerializer setValue:@"xxx" forHTTPHeaderField:@"Content-Type"];
		JsAfJSONResponseSerializer *responseSerializer = [JsAfJSONResponseSerializer serializer];
		responseSerializer.readingOptions = NSJSONReadingAllowFragments;
		_rawReqJsonResManager.responseSerializer = responseSerializer;
		_rawReqJsonResManager.responseSerializer.acceptableContentTypes =
		[NSSet setWithObjects:@"application/json", @"text/json",
		 @"text/javascript", @"text/html",
		 @"text/plain", nil];
	});
	return _rawReqJsonResManager;
}



+ (JsAfHTTPSessionManager *) sharedJsonManager {
	static JsAfHTTPSessionManager * _sharedJsonManager = nil;
	static dispatch_once_t onceToke;
	dispatch_once(&onceToke, ^{
		_sharedJsonManager = [JsAfHTTPSessionManager manager];
		
		_sharedJsonManager.requestSerializer = [JsAfJSONRequestSerializer serializer];
		[_sharedJsonManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
		JsAfJSONResponseSerializer *responseSerializer = [JsAfJSONResponseSerializer serializer];
		responseSerializer.readingOptions = NSJSONReadingAllowFragments;
		_sharedJsonManager.responseSerializer = responseSerializer;
		_sharedJsonManager.responseSerializer.acceptableContentTypes =
		[NSSet setWithObjects:@"application/json", @"text/json",
		 @"text/javascript", @"text/html",
		 @"text/plain", nil];
	});
	return _sharedJsonManager;
}



+ (NSString *)processedUrlWithOriginUrl:(NSString *)originUrl parameterArray:(NSArray *)array {
	if(array&&array.count) {
		NSString *parameterString = [array componentsJoinedByString:@"/"];
		originUrl = [NSString stringWithFormat:@"%@/%@",originUrl,parameterString];
	}
	return originUrl;
}

/**
 解析方式:
 req: urlencoding
 res: json
 */
+ (JsAfHTTPSessionManager *)sharedHreqJResManager {
	static JsAfHTTPSessionManager *_sharedSessionManager = nil;
	if (!_sharedSessionManager) {
		@synchronized(self) {
			if (!_sharedSessionManager) {
				_sharedSessionManager = [JsAfHTTPSessionManager manager];
				_sharedSessionManager.requestSerializer = [JsAfHTTPRequestSerializer serializer];
				
				JsAfJSONResponseSerializer *responseSerializer = [JsAfJSONResponseSerializer serializer];
				responseSerializer.readingOptions = NSJSONReadingAllowFragments;
				_sharedSessionManager.responseSerializer = responseSerializer;
				
				_sharedSessionManager.responseSerializer.acceptableContentTypes =
				[NSSet setWithObjects:@"application/json", @"text/json",
				 @"text/javascript", @"text/html",
				 @"text/plain", nil];
					// 超时设置
					//				_sharedSessionManager.requestSerializer.timeoutInterval = timeout;
				NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
				
				[_sharedSessionManager.requestSerializer setValue:@"iOS" forHTTPHeaderField:@"OS"];
				struct utsname systemInfo;
				uname(&systemInfo);
				NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
				[_sharedSessionManager.requestSerializer setValue:deviceString forHTTPHeaderField:@"MODEL"];
				NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];
				[_sharedSessionManager.requestSerializer setValue:phoneVersion forHTTPHeaderField:@"SYSTEM_VERSION"];
				[_sharedSessionManager.requestSerializer setValue:version forHTTPHeaderField:@"APP_VERSION"];
			}
		}
	}
	return _sharedSessionManager;
}

#pragma mark 2 Post
#pragma mark 2.1
#pragma mark POST请求--请求正文是键值对的形式,便利和完整的.

- (NSURLSessionDataTask *)postRequestByUrlencodedWithRequestConfig:(JsRequestConfig *) config
														completion:(JsResponseHandler)completion {
	JsAfHTTPSessionManager *manager = [self.class sharedManager];
	manager.requestSerializer.timeoutInterval = config.timeout.floatValue;
	
	JsRequestInfo * info = [JsRequestInfo new];
	info.requestStartTime = CFAbsoluteTimeGetCurrent();
	info.requestHeader = manager.requestSerializer.HTTPRequestHeaders;
	if(config.requestBodyInputType == JsRequestBodyInputTypeData){
		info.reqeustDataSize = ((NSData *)config.requestBodyInput).length;
	}
	//TODO:如果不是字典,需要再做处理.
	return [manager POST:[config requestUrlString] parameters:config.requestBodyInput headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:responseObject response:httpResponse error:nil config:config info:info completion:completion];
	} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:nil response:httpResponse error:error config:config info:info completion:completion];
	}];
}

#pragma mark post multipart/form-data
- (NSURLSessionDataTask *)postRequestByFormDataWithRequestConfig:(JsRequestConfig *) config
													  completion:(JsResponseHandler)completion {

	
	JsAfHTTPSessionManager *manager = [self.class sharedManager];
	manager.requestSerializer.timeoutInterval = config.timeout.floatValue;
	
	JsRequestInfo * info = [JsRequestInfo new];
	info.requestStartTime = CFAbsoluteTimeGetCurrent();
	info.requestHeader = manager.requestSerializer.HTTPRequestHeaders;
	
	return [manager POST:[config requestUrlString] parameters:config.requestBodyInput headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:responseObject response:httpResponse error:nil config:config info:info completion:completion];
	} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:nil response:httpResponse error:error config:config info:info completion:completion];
	}];
}

#pragma mark InnerFunc
- (void)addRequestHeaderForManager:(JsAfHTTPSessionManager *)manager fromConfig:(JsRequestConfig *)config {
		//设置请求头.
	if(config.requestHeader) {
		[config.requestHeader enumerateKeysAndObjectsUsingBlock:^(NSString *  _Nonnull key, NSString *  _Nonnull obj, BOOL * _Nonnull stop) {
			[manager.requestSerializer setValue:obj forHTTPHeaderField:key];
		}];
	}
}
#pragma mark post rawData
- (NSURLSessionDataTask *)postRequestByRawDataRequestConfig:(JsRequestConfig *)config
												  completion:(JsResponseHandler)completion {
		//设置manager,决定请求体和返回体的解析规则.
	JsAfHTTPSessionManager *manager = [self managerFromConfig:config];
	
	[self addRequestHeaderForManager:manager fromConfig:config];
		//TODO: 这样并不能每个接口单独一个超时时间吧?
	manager.requestSerializer.timeoutInterval = config.timeout.floatValue;
	
	JsRequestInfo * info = [JsRequestInfo new];
	info.requestStartTime = CFAbsoluteTimeGetCurrent();
	info.requestHeader = manager.requestSerializer.HTTPRequestHeaders;
	
		//2 调用JsAfN的网络处理,并调用统一的返回处理函数.
	return [manager POST:[config requestUrlString] parameters:config.requestBodyInput headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:responseObject response:httpResponse error:nil config:config info:info completion:completion];
	} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:nil response:httpResponse error:error config:config info:info completion:completion];
	}];
}

#pragma mark post application/json
//Todo:可以共用吗?
- (NSURLSessionDataTask *)postRequestByJsonWithRequestConfig:(JsRequestConfig *)config
												  completion:(JsResponseHandler)completion {
	//设置manager,决定请求体和返回体的解析规则.
	JsAfHTTPSessionManager *manager = [self.class sharedJsonManager];
	
	[self addRequestHeaderForManager:manager fromConfig:config];
		//TODO: 这样并不能每个接口单独一个超时时间吧?
	manager.requestSerializer.timeoutInterval = config.timeout.floatValue;
	
	JsRequestInfo * info = [JsRequestInfo new];
	info.requestStartTime = CFAbsoluteTimeGetCurrent();
	info.requestHeader = manager.requestSerializer.HTTPRequestHeaders;
	
	
		//2 调用JsAfN的网络处理,并调用统一的返回处理函数.
	return [manager POST:[config requestUrlString] parameters:config.requestBodyInput headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		info.responseHeader = httpResponse.allHeaderFields;
		[JsRequestUtil handleResponseObject:responseObject response:httpResponse error:nil config:config info:info completion:completion];
	} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:nil response:httpResponse error:error config:config info:info completion:completion];
	}];
}




//根据配置文件,得到maanger类型.
-(JsAfHTTPSessionManager *)managerFromConfig:(JsRequestConfig *)config {
	
		//配置reqeust解析.
	switch(config.requestBodyInputType) {
			//请求体没有数据,和data一样处理.
		case JsRequestBodyInputTypeNone:
		case JsRequestBodyInputTypeData:{
			//input data
			switch(config.responseBodyOutputType){
				case JsResponseBodyOutputTypeString:
				case JsResponseBodyOutputTypeData:{
					//string,data,自定义解析.
					return [self.class sharedManager];
				}
				case JsResponseBodyOutputTypeJsonToMap:
				case JsResponseBodyOutputTypeJsonToArray:{
					//map,array,使用 rawReqJsonResManager来处理.
					return [self.class sharedRawReqJsonResManager];
				}
			}
		}
		//TODO: 其他情况的还需要再完善.
		case JsRequestBodyInputTypeMapToJson:
			return [self.class sharedJsonManager];
		case JsRequestBodyInputTypeMapToFormdata:
		case JsRequestBodyInputTypeMapToUrlEncoded:
			return [self.class sharedManager];
	}
	
		//配置response解析
	switch(config.responseBodyOutputType){
		case JsResponseBodyOutputTypeString:
		case JsResponseBodyOutputTypeData:{
				//没有请求体,响应体为string,或者data,返回data.
			return [self.class sharedManager];
		}
		case JsResponseBodyOutputTypeJsonToMap:
		case JsResponseBodyOutputTypeJsonToArray:{
			
			return [self.class sharedJsonManager];
		}
	}
}

#pragma mark  01 get urlencode
- (NSURLSessionDataTask *)getRequestWithRequestConfig:(JsRequestConfig *) config info:(JsRequestInfo *)info
										   completion:(JsResponseHandler)completion {
	
	JsAfHTTPSessionManager *manager = [self managerFromConfig:config];

	manager.requestSerializer.timeoutInterval = config.timeout.floatValue;
	
	
	info.requestStartTime = CFAbsoluteTimeGetCurrent();
	
	[self addRequestHeaderForManager:manager fromConfig:config];

	return [manager GET:[config requestUrlString] parameters:config.requestBodyInput headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:responseObject response:httpResponse error:nil config:config info:info completion:completion];
	} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:nil response:httpResponse error:error config:config info:info completion:completion];
	}];
};






+ (NSString *)httpRequestMethodName:(JsRequestMethod)httpRequestMethod {
	NSArray *arrMethod = @[
		@"JsRequestMethodPost",
		@"HttpRequestMethodGet"
	];
	return arrMethod[httpRequestMethod];
}

- (NSString *)getTheTimeStamp {
	NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
	NSString *timestamp = [NSString stringWithFormat:@"%.0f", interval];
	return timestamp;
}
- (NSString *)ret32bitString

{
	char data[32];
	for (int x = 0; x < 32; data[x++] = (char)('A' + (arc4random_uniform(26))))
	;
	return [[NSString alloc] initWithBytes:data
									length:32
								  encoding:NSUTF8StringEncoding];
}

	//- (NSString *)getTheSignWithTimeStamp:(NSString *)timeStamp
	//							 noncestr:(NSString *)noncest {
	//	NSString *sign =
	//	[NSString stringWithFormat:@"ABCDEFGHIJKLMNOP%@%@", noncest, timeStamp];
	//	NSString *str2 = [MD5Util md5:sign];
	//	NSLog(@"str2 %@", str2);
	//	NSLog(@"sign %@", sign);
	//	return str2;
	//}

	//加密POST数据
+ (NSString *)encryptPostDataString:(NSString *)postDataString {
#if OPEN_ENCRYPTION
	NSString *encryptDataString =
	[EncryptorXXTEA XXTEAEncryptStr:postDataString key:kAESENCODEKEY];
	return encryptDataString;
#else
	return postDataString;
#endif
}

	//解密服务器返回数据
+ (NSDictionary *)decryptResponseData:(id)responseData {
	
#if OPEN_ENCRYPTION
	if ([responseData isKindOfClass:[NSDictionary class]]) {
		return responseData;
	}
	NSString *encryptDataString = responseData;
	NSDictionary *responseObject;
	NSString *responsStr =
	[EncryptorXXTEA XXTEADEncryptStr:encryptDataString key:kAESENCODEKEY];
	if (responsStr != nil && responsStr.length > 0) {
		responseObject = [NSJSONSerialization
						  JSONObjectWithData:[responsStr dataUsingEncoding:NSUTF8StringEncoding]
						  options:NSJSONReadingMutableLeaves
						  error:nil];
	} else {
		return nil;
	}
	return responseObject;
#else
	return responseData;
#endif
}


#pragma mark Delete
- (NSURLSessionDataTask *)deleteReqeustWithRequestConfig:(JsRequestConfig *) config
														completion:(JsResponseHandler)completion {
	JsAfHTTPSessionManager *manager = [JsAfHTTPSessionManager manager];
	
	switch(config.requestBodyInputType) {
		case JsRequestBodyInputTypeMapToJson:
		default:{
			JsAfJSONRequestSerializer * requestSerializer = [JsAfJSONRequestSerializer serializer];
			[requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
			manager.requestSerializer = requestSerializer;
			break;
		}
	}
	switch(config.responseBodyOutputType) {
		case JsResponseBodyOutputTypeJsonToMap:{
			JsAfJSONResponseSerializer *responseSerializer = [JsAfJSONResponseSerializer serializer];
			responseSerializer.readingOptions = NSJSONReadingAllowFragments;
			manager.responseSerializer = responseSerializer;
			manager.responseSerializer.acceptableContentTypes =
			[NSSet setWithObjects:@"application/json", @"text/json",
			 @"text/javascript", @"text/html",
			 @"text/plain", nil];
			break;
		}
		default:
			break;
	}
	
	
	manager.requestSerializer.timeoutInterval = config.timeout.floatValue;
	
	JsRequestInfo * info = [JsRequestInfo new];
	info.requestStartTime = CFAbsoluteTimeGetCurrent();
	info.requestHeader = manager.requestSerializer.HTTPRequestHeaders;
	if(config.requestBodyInputType == JsRequestBodyInputTypeData){
		info.reqeustDataSize = ((NSData *)config.requestBodyInput).length;
	}
		//TODO:如果不是字典,需要再做处理.
	return [manager DELETE:[config requestUrlString] parameters:config.requestBodyInput headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:responseObject response:httpResponse error:nil config:config info:info completion:completion];
	} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
		NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
		[JsRequestUtil handleResponseObject:nil response:httpResponse error:error config:config info:info completion:completion];
	}];
}
#pragma mark Options
- (NSURLSessionDataTask *)optionsReqeustWithRequestConfig:(JsRequestConfig *) config
											  completion:(JsResponseHandler)completion {
	return nil;
}
#pragma mark head
- (NSURLSessionDataTask *)headReqeustWithRequestConfig:(JsRequestConfig *) config
											   completion:(JsResponseHandler)completion {
	return nil;
}
#pragma mark put
- (NSURLSessionDataTask *)putReqeustWithRequestConfig:(JsRequestConfig *) config
											   completion:(JsResponseHandler)completion {
	return nil;
}
#pragma mark patch
- (NSURLSessionDataTask *)patchReqeustWithRequestConfig:(JsRequestConfig *) config
											   completion:(JsResponseHandler)completion {
	return nil;
}

#pragma mark trace
- (NSURLSessionDataTask *)traceReqeustWithRequestConfig:(JsRequestConfig *) config
											   completion:(JsResponseHandler)completion {
	return nil;
}
#pragma mark connect
- (NSURLSessionDataTask *)connectReqeustWithRequestConfig:(JsRequestConfig *) config
											   completion:(JsResponseHandler)completion {
	return nil;
}



@end
